import asyncio
from typing import Dict, Any, List
from datetime import datetime, timedelta

from database.mysql.video_crud import VideoTaskCRUD
from database.mysql.video_model import TaskStatus
from config.video_config import VIDEO_CONFIG
from config.logging_config import ProjectLoggers
from utils.file_helper import FileHelper

logger = ProjectLoggers.get_service_logger()

class TaskService:
    """任务管理服务类"""
    
    def __init__(self):
        self.running = False
        self.background_task = None
    
    async def start_background_service(self):
        """启动后台任务服务"""
        if self.running:
            logger.warning("后台任务服务已在运行中")
            return
        
        self.running = True
        self.background_task = asyncio.create_task(self._background_worker())
        logger.info("后台任务服务启动成功")
    
    async def stop_background_service(self):
        """停止后台任务服务"""
        if not self.running:
            return
        
        self.running = False
        if self.background_task:
            self.background_task.cancel()
            try:
                await self.background_task
            except asyncio.CancelledError:
                pass
        
        logger.info("后台任务服务已停止")
    
    async def _background_worker(self):
        """后台工作线程"""
        logger.info("后台任务工作线程启动")
        
        while self.running:
            try:
                # 执行定期任务
                await self._cleanup_expired_tasks()
                await self._cleanup_temp_files()
                await self._monitor_long_running_tasks()
                
                # 等待下一次检查（每5分钟执行一次）
                await asyncio.sleep(300)
                
            except asyncio.CancelledError:
                logger.info("后台任务工作线程被取消")
                break
            except Exception as e:
                logger.error(f"后台任务执行异常: {str(e)}")
                await asyncio.sleep(60)  # 出错时等待1分钟后重试
    
    async def _cleanup_expired_tasks(self):
        """清理过期任务"""
        try:
            # 查找超过24小时的失败任务和已完成任务
            cutoff_time = datetime.now() - timedelta(hours=24)
            
            # 这里应该添加一个查询过期任务的方法到CRUD中
            # 暂时跳过具体实现，因为需要修改CRUD
            
            logger.info("过期任务清理检查完成")
            
        except Exception as e:
            logger.error(f"清理过期任务失败: {str(e)}")
    
    async def _cleanup_temp_files(self):
        """清理临时文件"""
        try:
            cleaned_count = FileHelper.cleanup_temp_directory()
            if cleaned_count > 0:
                logger.info(f"清理了 {cleaned_count} 个临时文件")
                
        except Exception as e:
            logger.error(f"清理临时文件失败: {str(e)}")
    
    async def _monitor_long_running_tasks(self):
        """监控长时间运行的任务"""
        try:
            # 查找超过超时时间的处理中任务
            timeout_minutes = VIDEO_CONFIG['task_timeout'] // 60
            cutoff_time = datetime.now() - timedelta(minutes=timeout_minutes)
            
            # 这里应该查询长时间运行的任务并标记为失败
            # 暂时跳过具体实现
            
            logger.debug("长时间运行任务监控检查完成")
            
        except Exception as e:
            logger.error(f"监控长时间运行任务失败: {str(e)}")
    
    async def get_system_stats(self) -> Dict[str, Any]:
        """获取系统统计信息"""
        try:
            stats = {
                "service_running": self.running,
                "temp_directory": VIDEO_CONFIG['temp_dir'],
                "max_concurrent_tasks": VIDEO_CONFIG['max_concurrent_tasks'],
                "task_timeout_minutes": VIDEO_CONFIG['task_timeout'] // 60,
            }
            
            return {"success": True, "data": stats}
            
        except Exception as e:
            logger.error(f"获取系统统计信息失败: {str(e)}")
            return {"success": False, "error": str(e)}
    
    async def force_cleanup_task(self, task_id: str) -> Dict[str, Any]:
        """强制清理任务相关资源"""
        try:
            task = await VideoTaskCRUD.get_task_by_id(task_id)
            if not task:
                return {"success": False, "error": "任务不存在"}
            
            # 更新任务状态为失败
            if task.status in [TaskStatus.PENDING.value, TaskStatus.PROCESSING.value]:
                await VideoTaskCRUD.update_task_status(
                    task_id, TaskStatus.FAILED, error_message="系统强制清理"
                )
            
            logger.info(f"强制清理任务完成: {task_id}")
            return {"success": True, "message": "任务已清理"}
            
        except Exception as e:
            logger.error(f"强制清理任务失败 {task_id}: {str(e)}")
            return {"success": False, "error": str(e)}
    
    async def retry_failed_task(self, task_id: str) -> Dict[str, Any]:
        """重试失败的任务"""
        try:
            task = await VideoTaskCRUD.get_task_by_id(task_id)
            if not task:
                return {"success": False, "error": "任务不存在"}
            
            if task.status != TaskStatus.FAILED.value:
                return {"success": False, "error": "只能重试失败的任务"}
            
            # 重置任务状态
            await VideoTaskCRUD.update_task_status(
                task_id, TaskStatus.PENDING, progress=0, error_message=None
            )
            
            logger.info(f"任务重试设置完成: {task_id}")
            return {"success": True, "message": "任务已重置为待处理状态"}
            
        except Exception as e:
            logger.error(f"重试任务失败 {task_id}: {str(e)}")
            return {"success": False, "error": str(e)}
    
    async def get_task_queue_status(self) -> Dict[str, Any]:
        """获取任务队列状态"""
        try:
            # 获取各种状态的任务数量统计
            pending_tasks = await VideoTaskCRUD.get_pending_tasks(limit=100)
            
            # 按状态统计任务数量
            stats = {
                "pending_count": len(pending_tasks),
                "pending_tasks": [
                    {
                        "task_id": task.task_id,
                        "filename": task.original_filename,
                        "created_at": task.created_at.isoformat(),
                        "file_size": FileHelper.format_file_size(task.file_size) if task.file_size else "未知"
                    }
                    for task in pending_tasks[:10]  # 只返回前10个
                ]
            }
            
            return {"success": True, "data": stats}
            
        except Exception as e:
            logger.error(f"获取任务队列状态失败: {str(e)}")
            return {"success": False, "error": str(e)}

# 全局任务服务实例
task_service = TaskService() 